package com.xomily.devops.agent.util;

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.CentralProcessor.ProcessorIdentifier;
import oshi.hardware.CentralProcessor.TickType;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.NetworkIF;
import oshi.hardware.Sensors;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import com.xomily.devops.agent.domain.*;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

/**
 * @version V1.0
 * @ClassName:OshiUtil.java
 * @author: xomily (2327742507@qq.com)
 * @date: 2021年11月26日
 * @Description: OshiUtil.java
 * @Copyright: 2021-2022 www.xomily.com. All rights reserved.
 */
public class OshiUtil {
	private static final int OSHI_WAIT_SECOND = 1000;


	private static SystemInfo systemInfo = new SystemInfo();
	private static HardwareAbstractionLayer hal = systemInfo.getHardware();
 	

	/**
	 * 主机信息
	 */
	public static DevHost hostInfo() {
		DevHost host = new DevHost();
		CentralProcessor processor = hal.getProcessor();
	    ProcessorIdentifier pi=processor.getProcessorIdentifier();
		String cpuName = pi.getVendor()+' '+pi.getName();
		int cpuCores=processor.getPhysicalProcessorCount();
		Properties props = System.getProperties();
	    String osName = props.getProperty("os.name");
	    String osArch = props.getProperty("os.arch");
	    String hostName=(CommonUtil.getHostName());

		host.setCpu(cpuName);
		host.setHostname(hostName);
		host.setOs(osName);
		host.setArch(osArch);
        host.setCpuCores(cpuCores);		
		return host;
	}

	/**
	 * 磁盘信息
	 */
	public  static List<DevDisc> discInfo()
    {
    	List<DevDisc> discs = new LinkedList<DevDisc>();
    	OperatingSystem os=systemInfo.getOperatingSystem();
        FileSystem fileSystem = os.getFileSystem();
        List<OSFileStore> fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray)
        {
            DevDisc disc = new DevDisc();
            disc.setName(fs.getName());
            discs.add(disc);
        }
        return discs;
    }
    
	
	/**
     * 网卡信息
     */
	public  static List<DevNet> netInfo()
    {
    	List<DevNet> nets = new LinkedList<DevNet>();
    	List<NetworkIF> networkIFs = hal.getNetworkIFs();
    	for (NetworkIF netIf : networkIFs) {
    		DevNet net = new DevNet();
    		netIf.updateAttributes();
    		net.setName(netIf.getName());
    		net.setIp4addr( Arrays.toString(netIf.getIPv4addr()));
    		net.setIp6addr( Arrays.toString(netIf.getIPv6addr()));
    		net.setMacaddr(netIf.getMacaddr());		
    		nets.add(net);
    	}	
        return nets;
    }
	
	/**
	 * 内存使用记录
	 *
	 */
	public static DevMemLog memory() {

		DevMemLog memLog = new DevMemLog();
		GlobalMemory memory = hal.getMemory();
		memLog.setTotal(memory.getTotal());
		memLog.setUsed(memory.getTotal() - memory.getAvailable());
		memLog.setFree(memory.getAvailable());
		long total = memory.getTotal() / 1024L / 1024L;
		long used = (memory.getTotal() - memory.getAvailable()) / 1024L / 1024L;
		long free = memory.getAvailable() / 1024L / 1024L;
		double usePer = (double) (memory.getTotal() - memory.getAvailable()) / (double) memory.getTotal();
		memLog.setUseRate(CommonUtil.formatDouble(usePer * 100, 1));
		memLog.setTotal(total);
		memLog.setUsed(used);
		memLog.setFree(free);
		memLog.setGenerateTime(CommonUtil.getNow());

		return memLog;
	}

	/**
	 * CPU记录
	 */
	public static DevCpuLog cpu() {
		
		DevCpuLog cpuLog = new DevCpuLog();
		CentralProcessor processor = hal.getProcessor();
		Sensors sensors =hal.getSensors();
		long[] prevTicks = processor.getSystemCpuLoadTicks();
		Util.sleep(OSHI_WAIT_SECOND);
		long[] ticks = processor.getSystemCpuLoadTicks();
		long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
		long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
		long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
		long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
		long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
		long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
		long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
		long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
		long total=  user + nice + cSys + idle + iowait + irq + softirq + steal;
		double usePer = 1.0-(idle * 1.0 / total);
		double temperature =CommonUtil.formatDouble((double)sensors.getCpuTemperature(),1);
		String fan = Arrays.toString(sensors.getFanSpeeds());
		cpuLog.setNice(nice);
		cpuLog.setSteal(steal);
		cpuLog.setSys(cSys);
		cpuLog.setIowait(iowait);
		cpuLog.setIdle(idle);
		cpuLog.setUser(user);
		cpuLog.setIrq(irq);
		cpuLog.setSoft(softirq);
		cpuLog.setUseRate(CommonUtil.formatDouble(usePer * 100, 1));
		cpuLog.setFan(fan);
		cpuLog.setTemperature(temperature);
		cpuLog.setGenerateTime(CommonUtil.getNow());
		return cpuLog;
	}

    /**
     * 磁盘记录
     */
	public  static List<DevDiscLog> disc()
    {
    	List<DevDiscLog> discLogs = new LinkedList<DevDiscLog>();
    	OperatingSystem os=systemInfo.getOperatingSystem();
        FileSystem fileSystem = os.getFileSystem();
        List<OSFileStore> fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray)
        {
            long free = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            long used = total - free;
            double useRate=CommonUtil.formatDouble((double) 100* used / total,1);
            DevDiscLog discLog = new DevDiscLog();
            discLog.setName(fs.getName());
            discLog.setSize(CommonUtil.convertSize(total));
            discLog.setUsed(CommonUtil.convertSize(used));
            discLog.setUseRate(useRate);
            discLog.setGenerateTime(CommonUtil.getNow());
            discLogs.add(discLog);
        }
        return discLogs;
    }
    
    
    /**
     * 网络IO记录
     */
	public  static List<DevNetLog> net()
    {
    	List<DevNetLog> netLogs = new LinkedList<DevNetLog>();
    	List<NetworkIF> networkIFs = hal.getNetworkIFs();
    	for (NetworkIF netIf : networkIFs) {
    		DevNetLog netLog = new DevNetLog();
    		netIf.updateAttributes();
    		netLog.setName(netIf.getName());
    		long prevBytesRecv= netIf.getBytesRecv();
    		long prevPacketsRecv= netIf.getPacketsRecv();
    		long prevBytesSent= netIf.getBytesSent();
    		long prevPacketsSent= netIf.getPacketsSent();
    		Util.sleep(OSHI_WAIT_SECOND );
    		netIf.updateAttributes();
    		long rxbyt= netIf.getBytesRecv() - prevBytesRecv;
    		long rxpck= netIf.getPacketsRecv() - prevPacketsRecv ;
    		long txbyt= netIf.getBytesSent() -  prevBytesSent ;
    		long txpck= netIf.getPacketsSent() - prevPacketsSent;
    		long rxerr = netIf.getInErrors();
    		long txerr = netIf.getOutErrors();
    		netLog.setRxbyt(rxbyt);
    		netLog.setRxpck(rxpck);
    		netLog.setTxbyt(txbyt);
    		netLog.setTxpck(txpck);
    		netLog.setRxerr(rxerr);
    		netLog.setTxerr(txerr);    	
    		netLog.setGenerateTime(CommonUtil.getNow());
    		netLogs.add(netLog);
    	}	

        return netLogs;
    }
    
 

}
